package org.cybzacg.convert.strategy.impl;


import lombok.extern.slf4j.Slf4j;
import org.cybzacg.convert.context.ConversionContext;
import org.cybzacg.convert.core.TypeConverter;
import org.cybzacg.convert.enums.ConversionError;
import org.cybzacg.convert.enums.ConversionStrategyEnum;
import org.cybzacg.convert.exception.ConversionException;
import org.cybzacg.convert.strategy.ConversionStrategy;

/**
 * 安全转换策略
 * 提供额外的验证和安全检查，确保转换过程的安全性
 *
 * @author cybzacg.blog
 * @version 3.0
 * @since 3.0
 */
@Slf4j
public class SafeConversionStrategy implements ConversionStrategy {

    @Override
    public <T> T execute(
            TypeConverter converter,
            Object source,
            Class<T> targetType,
            T defaultValue,
            ConversionContext context
    ) throws ConversionException {

        // 安全检查
        if (!isSafeConversion(source, targetType, context)) {
            log.warn("检测到不安全的转换: {} -> {}",
                    source != null ? source.getClass().getSimpleName() : "null",
                    targetType.getSimpleName());
            return defaultValue;
        }

        try {
            // 执行转换
            T result = converter.convert(source, targetType, defaultValue, context);

            // 结果安全验证
            if (!isSafeResult(result, targetType)) {
                log.warn("转换结果不安全，使用默认值: {}", result);
                return defaultValue;
            }

            return result;

        } catch (ConversionException e) {
            // ConversionException 已经是包装过的异常，直接重新抛出
            log.error("安全模式下转换失败: {} -> {}, 错误: {}",
                    source, targetType.getSimpleName(), e.getMessage());
            throw e;

        } catch (Exception e) {
            log.error("安全模式下转换失败: {} -> {}, 错误: {}",
                    source, targetType.getSimpleName(), e.getMessage());

            // 对于严重错误，抛出异常
            if (isSevereError(e)) {
                throw new ConversionException(ConversionError.CONVERSION_FAILED,
                        "安全模式下发生严重错误: " + e.getMessage(), e);
            }

            // 对于一般错误，返回默认值
            return defaultValue;
        }
    }

    /**
     * 检查转换是否安全
     */
    private boolean isSafeConversion(Object source, Class<?> targetType, ConversionContext context) {
        // 检查源值安全性
        if (source != null) {
            // 检查是否为潜在危险类型
            if (isPotentiallyDangerousType(source.getClass())) {
                return false;
            }

            // 检查字符串长度
            if (source instanceof String) {
                String str = (String) source;
                if (str.length() > 10000) { // 限制字符串长度
                    return false;
                }
            }
        }

        // 检查目标类型安全性
        if (isPotentiallyDangerousType(targetType)) {
            return false;
        }

        // 检查转换深度
        if (context != null && context.getDepth() > 5) {
            return false;
        }

        return true;
    }

    /**
     * 检查结果是否安全
     */
    private boolean isSafeResult(Object result, Class<?> targetType) {
        if (result == null) {
            return true; // null值是安全的
        }

        // 检查结果类型
        if (!targetType.isInstance(result)) {
            return false;
        }

        // 检查字符串结果
        if (result instanceof String) {
            String str = (String) result;
            // 检查是否包含潜在危险内容
            if (containsDangerousContent(str)) {
                return false;
            }
        }

        return true;
    }

    /**
     * 检查是否为潜在危险类型
     */
    private boolean isPotentiallyDangerousType(Class<?> type) {
        // 检查是否为文件操作相关类型
        String typeName = type.getName();
        return typeName.startsWith("java.io.") ||
                typeName.startsWith("java.nio.") ||
                typeName.startsWith("java.net.") ||
                typeName.startsWith("java.lang.reflect.") ||
                typeName.startsWith("java.security.") ||
                typeName.startsWith("javax.script.");
    }

    /**
     * 检查字符串是否包含危险内容
     */
    private boolean containsDangerousContent(String str) {
        // 检查脚本注入
        if (str.toLowerCase().contains("<script") ||
                str.toLowerCase().contains("javascript:") ||
                str.toLowerCase().contains("vbscript:")) {
            return true;
        }

        // 检查SQL注入
        if (str.toLowerCase().contains("drop ") ||
                str.toLowerCase().contains("delete ") ||
                str.toLowerCase().contains("truncate ") ||
                str.toLowerCase().contains("exec(")) {
            return true;
        }

        return false;
    }

    /**
     * 检查是否为严重错误
     */
    private boolean isSevereError(Exception e) {
        log.debug("检查是否为严重错误: {} - {}", e.getClass().getSimpleName(), e.getMessage());

        // 检查是否为安全相关错误
        if (e instanceof SecurityException) {
            log.debug("检测到安全相关错误");
            return true;
        }

        // 检查是否为格式错误或转换错误
        if (e instanceof NumberFormatException) {
            log.debug("检测到NumberFormatException，认为是严重错误");
            return true;
        }

        if (e instanceof IllegalArgumentException) {
            log.debug("检测到IllegalArgumentException，认为是严重错误");
            return true;
        }

        if (e instanceof ConversionException) {
            log.debug("检测到ConversionException，认为是严重错误");
            return true;
        }

        // 检查错误消息是否包含严重关键词
        String message = e.getMessage();
        if (message != null) {
            String lowerMessage = message.toLowerCase();
            boolean containsKeywords = lowerMessage.contains("security") ||
                    lowerMessage.contains("access") ||
                    lowerMessage.contains("permission") ||
                    lowerMessage.contains("memory") ||
                    lowerMessage.contains("stack") ||
                    lowerMessage.contains("overflow") ||
                    lowerMessage.contains("format") ||
                    lowerMessage.contains("conversion") ||
                    lowerMessage.contains("parse");
            if (containsKeywords) {
                log.debug("错误消息包含严重关键词: {}", message);
                return true;
            }
        }

        log.debug("不认为是严重错误");
        return false;
    }

    @Override
    public ConversionStrategyEnum getName() {
        return ConversionStrategyEnum.SAFE;
    }

    @Override
    public String getDescription() {
        return "安全转换策略，提供额外的验证和安全检查，确保转换过程的安全性";
    }

    @Override
    public boolean supports(ConversionContext context) {
        return context != null && context.getStrategy().isSafe();
    }
}
